import { existsSync, readdirSync, readFileSync } from 'fs';
import { join } from 'path';
import { logger } from '../utils/logger';
import { CardRegistry } from '../registry/CardRegistry';
import { Card } from '../card/base/Card';
import { Room } from '../api/Room';
import { CardCommandExecutor } from './CardCommandExecutor';
import { IModJSON } from './Mod';
import { CardBuilding } from '../card/base/CardBuilding';

export class CardLoader {
	constructor(readonly mod: IModJSON) {}

	private defaultCard: Partial<any> = {
		pool: '',
		tags: [],
		type: this.mod.title,
		target: 'this',
		background: 'img/cards/default.png',
		title: '未命名的模组牌',
		desc: '',
		costPoint: 0,
		costMoney: 0,
		priority: 0,
	};

	loadCards(path: string) {
		if (!existsSync(path)) return;

		logger.info(`Loading cards from: ${path}`);
		readdirSync(path).forEach((value) => {
			const filePath = join(path, value);
			try {
				const json = JSON.parse(readFileSync(filePath, 'utf-8'));
				const data = { ...this.defaultCard, ...json };
				this.register(data);
			} catch (error) {
				logger.error(`Error loading card from ${filePath}: ${error}`);
			}
		});
	}

	private register(json: any) {
		const isBuilding = !!json.building;

		const CardClass = isBuilding ? CardBuilding : Card;

		class CardJSON extends CardClass {
			tags = json.tags;

			// 建筑效果

			progress: number = json.progress || 1;

			titleBuilding(room: Room, user: string): string {
				return typeof json.titleBuilding == 'string'
					? json.titleBuilding
					: this.execute('titleBuilding', room, user);
			}

			descBuilding(room: Room, user: string): string {
				return typeof json.descBuilding == 'string'
					? json.descBuilding
					: this.execute('descBuilding', room, user);
			}

			turnStartBuilding(room: Room, user: string): void {
				this.execute('turnStartBuilding', room, user);
			}

			turnEndBuilding(room: Room, user: string): void {
				this.execute('turnEndBuilding', room, user);
			}

			// 介绍效果

			canToField(room: Room, user: string) {
				return typeof json.canToField == 'boolean'
					? json.canToField
					: this.execute('canToField', room, user);
			}

			type(room: Room, user: string): string {
				return typeof json.type == 'string'
					? json.type
					: this.execute('type', room, user);
			}

			target(room: Room, user: string): string {
				return typeof json.target == 'string'
					? json.target
					: this.execute('target', room, user);
			}

			background(room: Room, user: string): string {
				return typeof json.background == 'string'
					? json.background
					: this.execute('background', room, user);
			}

			title(room: Room, user: string): string {
				if (isBuilding) return super.title(room, user);

				return typeof json.title == 'string'
					? json.title
					: this.execute('title', room, user);
			}

			desc(room: Room, user: string): string {
				if (isBuilding) return super.desc(room, user);
				return typeof json.desc == 'string'
					? json.desc
					: this.execute('desc', room, user);
			}

			costPoint(room: Room, user: string): number {
				return typeof json.costPoint == 'number'
					? json.costPoint
					: this.execute('costPoint', room, user);
			}

			costMoney(room: Room, user: string): number {
				return typeof json.costMoney == 'number'
					? json.costMoney
					: this.execute('costMoney', room, user);
			}

			// 效果效果

			turnStart(room: Room, user: string): void {
				if (isBuilding) return super.turnStart(room, user);
				this.execute('turnStart', room, user);
			}

			turnEnd(room: Room, user: string): void {
				if (isBuilding) return super.turnEnd(room, user);
				this.execute('turnEnd', room, user);
			}

			give(room: Room, user: string): void {
				this.execute('give', room, user);
			}

			use(room: Room, user: string, target: string): void {
				this.execute('use', room, user, target);
			}

			destroy(room: Room, user: string): void {
				this.execute('destroy', room, user);
			}

			// 电脑相关

			priority(room: Room, user: string, target: string): number {
				return typeof json.priority == 'number'
					? json.priority
					: this.execute(json.priority, room, user);
			}

			// 数据更新
			private execute(
				type: string,
				room: Room,
				user: string,
				target: string = '',
			) {
				const logic = json[type];
				if (!logic) return;
				const card = new CardCommandExecutor(room, user, target);
				return card.execute(logic);
			}
		}
		CardRegistry.register(json.id, CardJSON);
	}
}
